﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Xml.Linq;
using System.Linq;
using System.Windows.Resources;
using System.Collections.Generic;
using System.IO;
using System.Xml;

namespace WeatherFrame
{
    public class ImageIndex
    {
        public Dictionary<string, ConditionImageSet> condImageLookup = new Dictionary<string, ConditionImageSet>();

        public void Read(Stream str)
        {
            var xmlIndex = XElement.Load(str);
            foreach (var cond in xmlIndex.Descendants("cond"))
            {
                var condImgSet = new ConditionImageSet
                {
                    Name = (string)cond.Attribute("name")
                };
                Add(condImgSet);
                foreach (var photo in cond.Descendants("photo"))
                {
                    condImgSet.Images.Add(new ConditionImage { 
                        FlickrId = (string)photo.Attribute("id") ,
                        SmallUri = (string)photo.Attribute("smallUri") ,
                        Credit = (string)photo.Attribute("credit") ,
                        Title = (string)photo.Attribute("title"),
                    });
                }
            }
        }

        public void Write(Stream s)
        {
            XmlWriterSettings xws = new XmlWriterSettings { Indent = true };
            using (XmlWriter x = XmlWriter.Create(s, xws))
            {
                x.WriteStartDocument();
                x.WriteStartElement("conditions");
                foreach (var cond in condImageLookup.Values)
                {
                    WriteCondition(x, cond);
                }
                x.WriteEndElement();
                x.WriteEndDocument();
            }
        }

        private void WriteCondition(XmlWriter x, ConditionImageSet cond)
        {
            x.WriteStartElement("cond");
            x.WriteAttributeString("name", cond.Name);
            foreach (var im in cond.Images)
            {
                x.WriteStartElement("photo");
                x.WriteAttributeString("id", im.FlickrId);
                x.WriteAttributeString("smallUri", im.SmallUri);
                x.WriteAttributeString("credit", im.Credit);
                x.WriteAttributeString("title", im.Title);
                x.WriteEndElement();
            }
            x.WriteEndElement();
        }

        internal void Add(ConditionImageSet cis)
        {
            condImageLookup[cis.Name] = cis;
        }

        static internal Random rnd = new Random();

        /// <summary>
        /// Returns a random image for the specified key if hash is negative or a specific image
        /// if hash is positive.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hash"></param>
        /// <returns></returns>
        public ConditionImage GetImageForConditionKey(string key, int hash)
        {
            if (key == null) return null;
            if (!condImageLookup.ContainsKey(key)) return null;
            var cis = condImageLookup[key];
            //int i = (int)(rnd.NextDouble() * cis.Images.Count);
            return cis.NextImage(hash);
        }

        public ConditionImageSet GetImageSetForId(string id)
        {
            foreach (var cis in condImageLookup.Values)
            {
                if (cis.ContainsImage(id)) return cis;
            }
            return null;
        }
    }

    public class ConditionImageSet
    {
        public string Name { get; internal set; }

       public List<ConditionImage> Images { get; internal set; }
        public List<ConditionImage> AvailableImages { get; internal set; }

        public ConditionImageSet()
        {
            Images = new List<ConditionImage>();
        }

        internal ConditionImage NextImage(int hash)
        {
            if (Images.Count == 0) return null;
            if ((AvailableImages==null) || (AvailableImages.Count==0)) AvailableImages = new List<ConditionImage>(Images);
            int i = ImageIndex.rnd.Next(AvailableImages.Count);
            if (hash >= 0) i = hash % AvailableImages.Count;
            var res = AvailableImages[i];
            AvailableImages.RemoveAt(i);
            return res;
        }

        internal bool ContainsImage(string id)
        {
            return Images.FirstOrDefault(im => im.FlickrId.Equals(id)) != null;
        }
    }

    public class ConditionImage
    {
        internal int PickCount { get; set; }
        public string FlickrId { get; internal set; }
        public string SmallUri { get; internal set; }
        public string MediumUri { 
            get {
                if (SmallUri == null) return null;
                return SmallUri.Replace("_m.jpg", ".jpg");
            }
        }
        public string Title { get; internal set; }
        public string Credit { get; internal set; }
    }
}
